package com.hwtx.form.controller;

import com.google.common.collect.Maps;
import com.hwtx.form.annotation.Log;
import com.hwtx.form.annotation.OperationType;
import com.hwtx.form.domain.FormListService;
import com.hwtx.form.domain.service.FormService;
import com.hwtx.form.domain.vo.ResultVo;
import com.hwtx.form.dto.FormListQuery;
import com.hwtx.form.query.FormValueQuery;
import io.geekidea.boot.auth.cache.LoginCache;
import io.geekidea.boot.common.constant.SystemConstant;
import io.geekidea.boot.framework.exception.BusinessException;
import io.geekidea.boot.framework.response.ApiCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

import static com.hwtx.form.domain.FormConstants.*;

@Slf4j
@RestController
@Tag(name = "表单管理")
@RequestMapping(formPrefix)
public class FormController {

    @Resource
    private FormService formService;
    @Resource
    private FormListService formListService;

    @GetMapping("/load/{formId}")
    @Operation(summary = "获取表单定义(GET)")
    @Log(type = OperationType.GET, key = FORM_ID)
    public String load(@PathVariable Long formId, HttpServletRequest request, @RequestHeader(value = "locale", defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Exception {
        return loadPost(formId, request.getParameterMap(), locale);
    }

    @GetMapping("/action/load/{formType}/{action}")
    @Operation(summary = "获取表单片段)")
    @Log(type = OperationType.GET)
    public String actionLoad(@RequestParam MultiValueMap<String, Object> requestParam, @PathVariable String formType,
                             @PathVariable String action, @RequestHeader(value = "locale",
                    defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Throwable {
        if (StringUtils.isEmpty(formType)) {
            return Api2Result.build(ApiCode.FAIL, "表单类型不能为空", null);
        }
        if (StringUtils.isEmpty(action)) {
            return Api2Result.build(ApiCode.FAIL, "表单动作不能为空", null);
        }
        Map<String, Object> content = new HashMap<>();
        requestParam.forEach((key, values) -> content.put(key, values.isEmpty() ? null : values.getLast()));
        content.put(LOCALE_PARAM, locale);
        return Api2Result.build(ApiCode.SUCCESS, "加载成功", formService.action(formType, action, content).toString());
    }

    @PostMapping("/load/{formId}")
    @Operation(summary = "获取表单定义(POST)")
    @Log(type = OperationType.GET, key = FORM_ID)
    public String loadPost(@PathVariable Long formId, @RequestBody Map<String, String[]> content, @RequestHeader(value = "locale", defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Exception {
        Map<String, String[]> parameterMap = Maps.newHashMap(content);
        parameterMap.put(LOCALE_PARAM, new String[]{filterLocale(locale)});
        String formContent = formService.getStrFormDef(formId, parameterMap);
        return Api2Result.build(ApiCode.SUCCESS, "加载成功", formContent);
    }

    @PostMapping(Add)
    @Operation(summary = "新增表单数据")
    public Api2Result add(@RequestBody Map<String, Object> content) throws Exception {
        return save(content);
    }

    @PostMapping(Update)
    @Operation(summary = "更新表单数据")
    public Api2Result update(@RequestBody Map<String, Object> content) throws Exception {
        return save(content);
    }

    @PostMapping(AddOrUpdate)
    @Operation(summary = "更新/新增表单数据")
    public Api2Result addOrUpdate(@RequestBody Map<String, Object> content) throws Exception {
        return save(content);
    }

    @GetMapping("/app/{formType}/{action}")
    @Operation(summary = "执行表单动作（GET）")
    public Api2Result actionGet(@RequestParam MultiValueMap<String, Object> requestParam, @PathVariable String formType,
                                @PathVariable String action, @RequestHeader(value = "locale", defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Throwable {
        Map<String, Object> content = new HashMap<>();
        requestParam.forEach((key, values) -> content.put(key, values.isEmpty() ? null : values.getLast()));
        return action(content, formType, action, locale);
    }

    @PostMapping("/app/{formType}/{action}")
    @Operation(summary = "执行表单动作（POST）")
    public Api2Result action(@RequestBody Map<String, Object> content, @PathVariable String formType,
                             @PathVariable String action, @RequestHeader(value = "locale", defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Throwable {

        if (StringUtils.isEmpty(formType)) {
            return Api2Result.fail(ApiCode.FAIL, "表单类型不能为空");
        }
        if (StringUtils.isEmpty(action)) {
            return Api2Result.fail(ApiCode.FAIL, "表单动作不能为空");
        }
        content.put(LOCALE_PARAM, filterLocale(locale));
        Object ret = formService.action(formType, action, content);
        if (ret instanceof Boolean && !(Boolean) ret) {
            return Api2Result.fail(ApiCode.FAIL, "执行失败");
        }
        if (ret instanceof ResultVo resultVo) {
            if (resultVo.isSuccess()) {
                return Api2Result.result(ApiCode.SUCCESS, StringUtils.isBlank(resultVo.getMsg()) ? "执行成功" : resultVo.getMsg(), resultVo.getData());
            }
            return Api2Result.result(ApiCode.FAIL, resultVo.getMsg(), resultVo.getData());
        }
        return Api2Result.result(ApiCode.SUCCESS, "执行成功", ret);
    }

    private Api2Result save(Map<String, Object> content) throws Exception {
        Object formId = content.get(FORM_ID);
        if (formId == null) {
            return Api2Result.fail(ApiCode.FAIL, "表单ID不能为空");
        }
        Long fId;
        if (formId instanceof Integer) {
            fId = Long.valueOf((Integer) formId);
        } else {
            fId = Long.valueOf((String) formId);
        }
        Map<String, String> validationResult = formService.validateForm(fId, content);
        if (!validationResult.isEmpty()) {
            return Api2Result.validate(ApiCode.FAIL, "参数校验失败", validationResult);
        }
        try {
            Object ret = formService.saveFormData(fId, content, LoginCache.get().getUsername());
            if (ret instanceof Boolean result && result) {
                return Api2Result.result(ApiCode.SUCCESS, "保存成功", Api2Result.ResVo.builder().ret(true).build());
            } else if (ret instanceof String result) {
                return Api2Result.result(ApiCode.SUCCESS, result, Api2Result.ResVo.builder().ret(ret).build());
            } else if (ret instanceof ResultVo resultVo) {
                if (resultVo.isSuccess()) {
                    return Api2Result.result(ApiCode.SUCCESS, resultVo.getMsg(), resultVo.getData());
                }
                return Api2Result.fail(ApiCode.FAIL, resultVo.getMsg());
            }
        } catch (BusinessException e) {
            return Api2Result.fail(ApiCode.FAIL, e.getMessage());
        }
        return Api2Result.fail(ApiCode.FAIL, "保存失败");
    }

    @GetMapping(Get)
    @Operation(summary = "获取表单数据")
    public Api2Result get(FormValueQuery formValueQuery, HttpServletRequest request, @RequestHeader(value = "locale", defaultValue = SystemConstant.DEFAULT_LOCALE) String locale) throws Exception {
        if (CollectionUtils.isEmpty(formValueQuery.getValueIds())) {
            Api2Result.result(ApiCode.SUCCESS, "加载成功", "");
        }
        if (formValueQuery.getValueIds().size() > 1) {
            return Api2Result.fail("数据标识只能唯一");
        }
        formValueQuery.setLocale(filterLocale(locale));
        formValueQuery.setParameters(request.getParameterMap());
        return Api2Result.result(ApiCode.SUCCESS, "加载成功", formService.getFormData(formValueQuery).getData());
    }

    @RequestMapping(value = Remove, method = RequestMethod.POST)
    @Operation(summary = "删除表单数据")
    public Api2Result remove(FormValueQuery formValueQuery, HttpServletRequest request) throws Exception {
        if (CollectionUtils.isEmpty(formValueQuery.getValueIds())) {
            return Api2Result.result(ApiCode.FAIL, "数据ID不能为空", "");
        }
        formValueQuery.setParameters(request.getParameterMap());
        Object ret = formService.remove(formValueQuery);
        if (ret instanceof Boolean result && result) {
            return Api2Result.result(ApiCode.SUCCESS, "删除成功", "");
        } else if (ret instanceof String result) {
            return Api2Result.result(ApiCode.SUCCESS, result, Api2Result.ResVo.builder().ret(ret).build());
        }
        return Api2Result.fail(ApiCode.FAIL, ret.toString());
    }

    @GetMapping(List_Req)
    @Operation(summary = "获取表单中列表数据")
    public Api2Result list(FormListQuery formListQuery, HttpServletRequest request) throws Exception {
        if (formListQuery.getFormId() == null) {
            return Api2Result.fail("表单ID不能为空");
        }
        formListQuery.setSearchData(request.getParameterMap());
        Map<String, Object> convertedMap = new HashMap<>();
        for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
            if (!DEFAULT_PAGE_QUERY_PARAM.contains(entry.getKey())) {
                convertedMap.put(entry.getKey(), entry.getValue()[0] == null ? "" : entry.getValue()[0]);
            }
        }
        formListQuery.setSearchPostData(convertedMap);
        return Api2Result.result(ApiCode.SUCCESS, "加载成功", formListService.list(formListQuery));
    }

    @PostMapping(Page)
    @Operation(summary = "分页获取表单中列表数据")
    public Api2Result page(@RequestBody Map<String, Object> data) throws Exception {
        if (data.get(FORM_ID) == null) {
            return Api2Result.fail("表单ID不能为空");
        }
        FormListQuery formListQuery = new FormListQuery();
        Object fId = data.get(FORM_ID);
        if (fId instanceof Integer) {
            formListQuery.setFormId(Long.valueOf((Integer) fId));
        } else {
            formListQuery.setFormId(Long.valueOf((String) fId));
        }
        formListQuery.setSearchPostData(data);
        formListQuery.setPageIndex((Integer) data.get(PAGE_INDEX));
        formListQuery.setPageSize((Integer) data.get(PAGE_SIZE));
        formListQuery.setOrderByAsc((Boolean) data.get(ORDER_BY_ASC));
        formListQuery.setOrderByColumn((String) data.get(ORDER_BY_COLUMN));
        DEFAULT_PAGE_QUERY_PARAM.forEach(data::remove);
        return Api2Result.result(ApiCode.SUCCESS, "加载成功", formListService.page(formListQuery));
    }

    private String filterLocale(String locale) {
        if (locale.startsWith("\"") && locale.endsWith("\"")) {
            locale = locale.substring(1, locale.length() - 1);
        }
        return locale;
    }
}
